__doc__ =   """ AbstractPropertyDict provides abstract classes to hold results
                of property analyses of entities.
            """

from Einput import einput   # standard input
from itertools import izip      # iter without list building
from numpy import (array, mean)


class AbstractPropertyDict(dict):
    """ PropertyDict base class. Common methods for subclasses for entities
        of different levels.
    """
    def array(self, *args, **kwargs):
        """ Returns and array from from values.
        """
        return array(self.values(), *args, **kwargs)

    def sorted_array(self, *args, **kwargs):
        """ Array of sorted values.
        """
        return array(self.sorted_values(), *args, **kwargs)

    def average(self):
        """ The average value. Meaningful only if values are numeric.
        """
        return mean(self.values())

    def sorted_values(self):
        """ Values sorted lexicographically.
        """
        return list(sorted(self.values()))

class AbstractStructurePropertyDict(AbstractPropertyDict):
    """ PropertyDict for structures.
    """
    pass


class AbstractResiduePropertyDict(AbstractPropertyDict):
    """ PropertyDict for residues.
    """
    pass


class AbstractAtomPropertyDict(AbstractPropertyDict):
    """ PropertyDict for atoms.
    """
    pass


class AbstractHolderPropertyDict(AbstractPropertyDict):
    """ PropertyDict for Holder entities.
    """
    pass


class AttributeDict(AbstractPropertyDict):
    """ Class to get attributes of attribues.
    """
    def __init__(self, entities, attr, level, key =None):
        ents = einput(entities, level)
        if key:
            attrs = ((id, getattr(ent, attr)[key]) for (id, ent) in ents.iteritems() if key in getattr(ent, attr))
        else:
            attrs = ((id, getattr(ent, attr)) for (id, ent) in ents.iteritems())
        AbstractPropertyDict.__init__(self, attrs)


class AtomAttributeDict(AbstractAtomPropertyDict):
    """ Class to retrieve attribute of atoms of a given entity.
    """
    def __init__(self, entities, attr, key =None):
        level = 'A'
        attribute_dict = AttributeDict(entities, attr, level, key)
        AbstractAtomPropertyDict.__init__(self, attribute_dict)


class ResidueAttributeDict(AbstractResiduePropertyDict):
    """ Class to retrieve attribute of residues of a given entity.
    """
    def __init__(self, entities, attr, key =None):
        level = 'R'
        attribute_dict = AttributeDict(entities, attr, level, key)
        AbstractResiduePropertyDict.__init__(self, attribute_dict)

#EOF